/*-
 * Copyright (c) 2012-2013 Shang-Rong Cai. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $ MTBLAS TEST: tst_lv_1_scl.c    Rev. 0.0.5    2013-10-10T14:36+08:00 $
 */

#include <stdio.h>
#include <complex.h>

#include <cblas.h>

#include <tst_lv_a_com.h>

int test_scalf(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    float alpha;
    vec_ff_t vx;
    vec_ff_t vy;

    float buf_st;  /* Single-thread return */
    float buf_mt;  /* Multi-threads return */
    float buf_cf;  /* cblas return */

    alpha = random_float();
    ierr = vec_ff_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vx);

    ierr = vec_ff_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = stblas_copyf(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = stblas_scalf(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = stblas_nrm2f(PROPER_VECTOR_RUN, vy.data, vy.step, &buf_st);
    ierr = vec_ff_delete(&vy);

    ierr = vec_ff_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = mtblas_copyf(thrz, PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = mtblas_scalf(thrz, PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = mtblas_nrm2f(thrz, PROPER_VECTOR_RUN, vy.data, vy.step, &buf_mt);
    ierr = vec_ff_delete(&vy);

    ierr = vec_ff_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    cblas_scopy(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    cblas_sscal(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    buf_cf = cblas_snrm2(PROPER_VECTOR_RUN, vy.data, vy.step);
    ierr = vec_ff_delete(&vy);

    printf("scalf() -> cblas_sscal()\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    ierr = vec_ff_delete(&vx);

    return ierr;
}


int test_scal(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    double alpha;
    vec_df_t vx;
    vec_df_t vy;

    double buf_st;  /* Single-thread return */
    double buf_mt;  /* Multi-threads return */
    double buf_cf;  /* cblas return */

    alpha = random_double();
    ierr = vec_df_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vx);

    ierr = vec_df_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = stblas_copy(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = stblas_scal(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = stblas_nrm2(PROPER_VECTOR_RUN, vy.data, vy.step, &buf_st);
    ierr = vec_df_delete(&vy);

    ierr = vec_df_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = mtblas_copy(thrz, PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = mtblas_scal(thrz, PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = mtblas_nrm2(thrz, PROPER_VECTOR_RUN, vy.data, vy.step, &buf_mt);
    ierr = vec_df_delete(&vy);

    ierr = vec_df_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    cblas_dcopy(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    cblas_dscal(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    buf_cf = cblas_dnrm2(PROPER_VECTOR_RUN, vy.data, vy.step);
    ierr = vec_df_delete(&vy);

    printf("scal() -> cblas_dscal()\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    ierr = vec_df_delete(&vx);

    return ierr;
}


int test_scall(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    long double alpha;
    vec_lf_t vx;
    vec_lf_t vy;

    long double buf_st;  /* Single-thread return */
    long double buf_mt;  /* Multi-threads return */

    alpha = random_long_double();
    ierr = vec_lf_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vx);

    ierr = vec_lf_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = stblas_copyl(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = stblas_scall(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = stblas_nrm2l(PROPER_VECTOR_RUN, vy.data, vy.step, &buf_st);
    ierr = vec_lf_delete(&vy);

    ierr = vec_lf_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = mtblas_copyl(thrz, PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = mtblas_scall(thrz, PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = mtblas_nrm2l(thrz, PROPER_VECTOR_RUN, vy.data, vy.step, &buf_mt);
    ierr = vec_lf_delete(&vy);

    printf("scall()\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    ierr = vec_lf_delete(&vx);

    return ierr;
}


int test_cscalf(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    float complex alpha;
    vec_fc_t vx;
    vec_fc_t vy;

    float buf_st;  /* Single-thread return */
    float buf_mt;  /* Multi-threads return */
    float buf_cf;  /* cblas return */

    alpha = random_float() + random_float() * _Complex_I;
    ierr = vec_fc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vx);

    ierr = vec_fc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = stblas_ccopyf(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = stblas_cscalf(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = stblas_cnrm2f(PROPER_VECTOR_RUN, vy.data, vy.step, &buf_st);
    ierr = vec_fc_delete(&vy);

    ierr = vec_fc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = mtblas_ccopyf(thrz, PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = mtblas_cscalf(thrz, PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = mtblas_cnrm2f(thrz, PROPER_VECTOR_RUN, vy.data, vy.step, &buf_mt);
    ierr = vec_fc_delete(&vy);

    ierr = vec_fc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    cblas_ccopy(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    cblas_cscal(PROPER_VECTOR_RUN, (void*) &alpha, vy.data, vy.step);
    buf_cf = cblas_scnrm2(PROPER_VECTOR_RUN, vy.data, vy.step);
    ierr = vec_fc_delete(&vy);

    printf("cscalf() -> cblas_cscal()\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    ierr = vec_fc_delete(&vx);

    return ierr;
}


int test_cscal(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    double complex alpha;
    vec_dc_t vx;
    vec_dc_t vy;

    double buf_st;  /* Single-thread return */
    double buf_mt;  /* Multi-threads return */
    double buf_cf;  /* cblas return */

    alpha = random_double() + random_double() * _Complex_I;
    ierr = vec_dc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vx);

    ierr = vec_dc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = stblas_ccopy(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = stblas_cscal(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = stblas_cnrm2(PROPER_VECTOR_RUN, vy.data, vy.step, &buf_st);
    ierr = vec_dc_delete(&vy);

    ierr = vec_dc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = mtblas_ccopy(thrz, PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = mtblas_cscal(thrz, PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = mtblas_cnrm2(thrz, PROPER_VECTOR_RUN, vy.data, vy.step, &buf_mt);
    ierr = vec_dc_delete(&vy);

    ierr = vec_dc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    cblas_zcopy(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    cblas_zscal(PROPER_VECTOR_RUN, (void*) &alpha, vy.data, vy.step);
    buf_cf = cblas_dznrm2(PROPER_VECTOR_RUN, vy.data, vy.step);
    ierr = vec_dc_delete(&vy);

    printf("cscal() -> cblas_zscal()\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    ierr = vec_dc_delete(&vx);

    return ierr;
}


int test_cscall(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    long double complex alpha;
    vec_lc_t vx;
    vec_lc_t vy;

    long double buf_st;  /* Single-thread return */
    long double buf_mt;  /* Multi-threads return */

    alpha = random_long_double() + random_long_double() * _Complex_I;
    ierr = vec_lc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vx);

    ierr = vec_lc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = stblas_ccopyl(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = stblas_cscall(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = stblas_cnrm2l(PROPER_VECTOR_RUN, vy.data, vy.step, &buf_st);
    ierr = vec_lc_delete(&vy);

    ierr = vec_lc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = mtblas_ccopyl(thrz, PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = mtblas_cscall(thrz, PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = mtblas_cnrm2l(thrz, PROPER_VECTOR_RUN, vy.data, vy.step, &buf_mt);
    ierr = vec_lc_delete(&vy);

    printf("cscall()\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    ierr = vec_lc_delete(&vx);

    return ierr;
}


int test_fcscalf(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    float alpha;
    vec_fc_t vx;
    vec_fc_t vy;

    float buf_st;  /* Single-thread return */
    float buf_mt;  /* Multi-threads return */
    float buf_cf;  /* cblas return */

    alpha = -random_float();
    ierr = vec_fc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vx);

    ierr = vec_fc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = stblas_ccopyf(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = stblas_fcscalf(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = stblas_cnrm2f(PROPER_VECTOR_RUN, vy.data, vy.step, &buf_st);
    ierr = vec_fc_delete(&vy);

    ierr = vec_fc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = mtblas_ccopyf(thrz, PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = mtblas_fcscalf(thrz, PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = mtblas_cnrm2f(thrz, PROPER_VECTOR_RUN, vy.data, vy.step, &buf_mt);
    ierr = vec_fc_delete(&vy);

    ierr = vec_fc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    cblas_ccopy(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    cblas_csscal(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    buf_cf = cblas_scnrm2(PROPER_VECTOR_RUN, vy.data, vy.step);
    ierr = vec_fc_delete(&vy);

    printf("fcscalf() -> cblas_csscal()\n");
    check_value_ff_stdout("    ST:", buf_st);
    check_value_ff_stdout("    MT:", buf_mt);
    check_value_ff_stdout("    CF:", buf_cf);

    ierr = vec_fc_delete(&vx);

    return ierr;
}


int test_fcscal(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    double alpha;
    vec_dc_t vx;
    vec_dc_t vy;

    double buf_st;  /* Single-thread return */
    double buf_mt;  /* Multi-threads return */
    double buf_cf;  /* cblas return */

    alpha = -random_double();
    ierr = vec_dc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vx);

    ierr = vec_dc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = stblas_ccopy(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = stblas_fcscal(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = stblas_cnrm2(PROPER_VECTOR_RUN, vy.data, vy.step, &buf_st);
    ierr = vec_dc_delete(&vy);

    ierr = vec_dc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = mtblas_ccopy(thrz, PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = mtblas_fcscal(thrz, PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = mtblas_cnrm2(thrz, PROPER_VECTOR_RUN, vy.data, vy.step, &buf_mt);
    ierr = vec_dc_delete(&vy);

    ierr = vec_dc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    cblas_zcopy(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    cblas_zdscal(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    buf_cf = cblas_dznrm2(PROPER_VECTOR_RUN, vy.data, vy.step);
    ierr = vec_dc_delete(&vy);

    printf("cscal() -> cblas_zdscal()\n");
    check_value_df_stdout("    ST:", buf_st);
    check_value_df_stdout("    MT:", buf_mt);
    check_value_df_stdout("    CF:", buf_cf);

    ierr = vec_dc_delete(&vx);

    return ierr;
}


int test_fcscall(size_t thrz)
{
    int ierr = ERRNO_UNDEFINED;

    long double alpha;
    vec_lc_t vx;
    vec_lc_t vy;

    long double buf_st;  /* Single-thread return */
    long double buf_mt;  /* Multi-threads return */

    alpha = -random_long_double();
    ierr = vec_lc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vx);

    ierr = vec_lc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = stblas_ccopyl(PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = stblas_fcscall(PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = stblas_cnrm2l(PROPER_VECTOR_RUN, vy.data, vy.step, &buf_st);
    ierr = vec_lc_delete(&vy);

    ierr = vec_lc_create(PROPER_VECTOR_MAX, PROPER_VECTOR_MIN, PROPER_VECTOR_RUN, &vy);
    ierr = mtblas_ccopyl(thrz, PROPER_VECTOR_RUN, vx.data, vx.step, vy.data, vy.step);
    ierr = mtblas_fcscall(thrz, PROPER_VECTOR_RUN, alpha, vy.data, vy.step);
    ierr = mtblas_cnrm2l(thrz, PROPER_VECTOR_RUN, vy.data, vy.step, &buf_mt);
    ierr = vec_lc_delete(&vy);

    printf("cscall()\n");
    check_value_lf_stdout("    ST:", buf_st);
    check_value_lf_stdout("    MT:", buf_mt);

    ierr = vec_lc_delete(&vx);

    return ierr;
}
